package api

import (
	"fmt"
	"log"
	"mytest/Internal/middleware"
	"mytest/initialize/database"
	"mytest/models"
	"mytest/models/request"
	"mytest/service/system"
	"net/http"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/go-redis/redis"

	"github.com/gin-gonic/gin"
)

func Login(c *gin.Context) {
	var L request.Login
	if err := c.Bind(&L); err != nil {
		c.String(http.StatusBadRequest, "%v", err.Error())
		return
	}
	user, err := system.CheckLogin(L)
	if err != nil {
		//c.String(http.StatusOK, "密码错误%v", err.Error())
		c.JSON(http.StatusOK, UniversalResp{
			Code: 400,
			Msg:  fmt.Sprintf("账号或密码错误"),
		})
	} else {
		//分发token
		GiveToken(c, *user)
	}
}
func Register(c *gin.Context) {
	var L request.Login
	if err := c.Bind(&L); err != nil {
		c.String(http.StatusBadRequest, "%v", err.Error())
		return
	}
	u := models.SysUser{
		Username:    L.Username,
		Password:    L.Password,
		AuthorityId: "001",
		NickName:    "普通用户",
	}
	user, err := system.RegisterLogin(u)
	if err != nil {
		c.JSON(http.StatusOK, UniversalResp{
			Code: 1,
			Msg:  err.Error(),
			Data: user,
		})
		return
	}
	c.JSON(http.StatusOK, UniversalResp{
		Msg:  "注册成功",
		Data: user,
	})

}
func DeleteUser(c *gin.Context) {
	var id request.GetById
	if err := c.Bind(&id); err != nil {
		c.String(http.StatusBadRequest, "%v", err.Error())
		return
	}
	if id.Id == 0 {
		c.String(http.StatusOK, "请传入id")
		return
	}
	if claim, exists := c.Get("claims"); !exists {
		c.String(http.StatusOK, "从Gin的Context中获取从jwt解析出来的用户ID失败, 请检查路由是否使用jwt中间件")
		return
	} else {
		uid := claim.(*request.CustomClaims).ID
		log.Println(claim.(*request.CustomClaims))
		if uid == id.Id {
			c.String(http.StatusOK, "自杀失败")
			return
		}
	}
	err := system.DeleteUser(database.GetDB(), id.Id)
	if err != nil {
		c.String(http.StatusOK, "%v", err.Error())
		return
	}
	c.JSON(http.StatusOK, UniversalResp{
		Msg: "删除成功",
	})
}
func ChangePassword(c *gin.Context) {
	var r request.ChangePassword
	if err := c.Bind(&r); err != nil {
		c.String(http.StatusBadRequest, "%v", err.Error())
		return
	}
	err := system.SetPassword(database.GetDB(), r)
	if err != nil {
		c.String(http.StatusOK, "%v", err.Error())
		return
	}
	c.JSON(http.StatusOK, UniversalResp{
		Msg: "修改成功",
	})
}
func LogOut(c *gin.Context) {
	token := c.Request.Header.Get("token")
	_ = system.JornBlackList(token)

}

//颁发token
func GiveToken(c *gin.Context, user models.SysUser) {
	j := middleware.NewJWT()
	claims := request.CustomClaims{
		ID:          user.ID,
		UUID:        user.UUID,
		NickName:    user.NickName,
		Username:    user.Username,
		AuthorityId: user.AuthorityId,
		BufferTime:  60 * 60 * 24, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
		StandardClaims: jwt.StandardClaims{
			NotBefore: time.Now().Unix() - 1000,       //签名生效时间
			ExpiresAt: time.Now().Unix() + 60*60*24*7, // 过期时间 7天
			Issuer:    "ChenWei",                      // 签名的发行者
		},
	}

	token, err := j.CreateToken(claims)
	if err != nil {
		c.String(http.StatusOK, "创建token失败%v", err.Error())
		return
	}

	// 如果多点登录
	//c.JSON(http.StatusOK, UniversalResp{
	//	Data: token,
	//	Msg:  "登陆成功",
	//})

	//为了单点登录
	if err, oldjwt := system.GetRedisJWT(user.Username); err == redis.Nil {
		//第一次登录
		if err = system.SetRedisJWT(user.Username, token); err != nil {
			c.String(http.StatusOK, "设置登陆状态失败%v", err.Error())
			return
		}
		c.JSON(http.StatusOK, UniversalResp{
			Data: gin.H{"user": user, "token": token},
			Msg:  "登陆成功",
		})
	} else if err != nil {
		c.String(http.StatusOK, "设置登陆状态失败%v", err.Error())
	} else {
		//另一个点 登录,先把以前的加入黑名单
		log.Println("old jwt:", oldjwt)
		err = system.JornBlackList(oldjwt)
		if err != nil {
			c.String(http.StatusOK, "设置登陆状态失败%v", err.Error())
			return
		}
		log.Println("new jwt:", token)
		if err = system.SetRedisJWT(user.Username, token); err != nil {
			c.String(http.StatusOK, "设置登陆状态失败%v", err.Error())
			return
		}
		c.JSON(http.StatusOK, UniversalResp{
			Data: gin.H{"user": user, "token": token},
			Msg:  "登陆成功",
		})
	}
}
